import React, { useState, useEffect } from 'react'
import { Son } from './son'
import img from '../../assets/react生命周期.png'
const boxStyle = {
  margin: '10px',
  border: '1px solid #ccc',
  borderRadius: '10px',
}
const flexBox = {
  display: 'flex',
  justifyContent: 'space-around',
  flexWrap: 'wrap',
}

// 在react中state修改都会重新执行rander函数, render函数执行时也会默认update子组件(未优化),即使state未用于函数渲染也会触发
// 非state数据不会触发, 如class组件其它实例属性, React.createRef 也不会触发
// ref虽然不会触发render, 但是在函数组件中能触发useEffect

// 父子生命周期流程:
// father__getDerivedStateFromProps
// father__shouldComponentUpdate
// father__render...

// Son----getDerivedStateFromProps 
// Son----shouldComponentUpdate 
// Son----render
// son__getSnapshotBeforeUpdate
// father__getSnapshotBeforeUpdate
// Son----componentDidUpdate

// father__componentDidUpdate

export class Father extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      noSendState: 20,
      sendState: 22,
      sonKey: 1,
    }
    this.changenoSendState = this.changenoSendState.bind(this)
    this.changeSendState = this.changeSendState.bind(this)
    this.forceUpdateSon = this.forceUpdateSon.bind(this)
    this.updateSonByKey = this.updateSonByKey.bind(this)
    // ref属性只会在初次生成实例时挂载,后面不更新, 除非手动重新卸载挂载组件
    this.myRef = React.createRef()
    this.instanceData = 1
    // 使用回调 Refs 设置ref, 可以设置在其它位置,储存在实例属性上,state上
    this.fnSetRef = null
    this.setRefFn = (element) => {
      this.fnSetRef = element
    }
  }

  // ++++++++++++++++++ 生命周期 ++++++++++
  static getDerivedStateFromProps(props, state) {
    // console.log('father__getDerivedStateFromProps')
    return null
  }
  shouldComponentUpdate(nextProps, nextState) {
    // console.log('father__shouldComponentUpdate')
    return true
  }
  //  render()
  getSnapshotBeforeUpdate(prevProps, prevState) {
    // console.log('father__getSnapshotBeforeUpdate')
    return 111222333
  }
  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log('father__componentDidUpdate')
  }

  // ++++++++++++++++++++++ 函数 +++++++++++
  changenoSendState() {
    console.log(
      'father__changenoSendState',
      this.instanceData,
      this.myRef,
      this.fnSetRef
    )
    this.setState({
      noSendState: this.state.noSendState + 1,
    })
  }
  changeSendState() {
    this.setState({
      sendState: this.state.sendState + 1,
    })
  }
  // 通过refs和forceUpdate手动跟新子组件
  forceUpdateSon() {
    // 通过forceUpdate更新子组件 会跳过其shouldComponentUpdate生命周期
    console.log('forceUpdateSon', this.myRef, this.fnSetRef)
    this.myRef &&
      this.myRef.current &&
      this.myRef.current.forceUpdate(() => {
        console.log('son组件已手动更新...')
      })
    this.fnSetRef.forceUpdate(() => {
      console.log('son组件已手动更新...')
    })
  }
  // 通过key来更新子组件, 子组件会重新挂载
  updateSonByKey() {
    this.setState({
      sonKey: this.state.sonKey + 1,
    })
  }
  // 改变实例上的值
  updateInstaceData() {
    this.instanceData = this.instanceData + 1
  }
  reseatRef() {
    this.myRef.current = new Date();
    this.fnSetRef = null
  }
  render() {
    // console.log('father__render...')
    return (
      <div style={boxStyle}>
        <img style={{ width: '820px', height: '600px', padding: '10px' }} src={img} alt="" />
        <p>这是father组件</p> <span>这是instanceData值: {this.instanceData}</span>
        <div style={flexBox}>
          <button style={{ marginBottom: '10px' }} onClick={this.changenoSendState}>
            father不传递的state:{this.state.noSendState}
          </button>
          <button style={{ marginBottom: '10px' }} onClick={this.changeSendState}>
            father传递的state:{this.state.sendState}
          </button>
          <button style={{ marginBottom: '10px' }} onClick={this.forceUpdateSon}>
            forceUpdate更新son组件
          </button>
          <button style={{ marginBottom: '10px' }} onClick={this.updateSonByKey}>
            key更新son组件
          </button>
          <button style={{ marginBottom: '10px' }} onClick={() => this.updateInstaceData()}>
            更新updateInstaceData
          </button>
          <button style={{ marginBottom: '10px' }} onClick={() => this.reseatRef()}>
            重置ref为null
          </button>
        </div>
        {/* 组件上key不会被作为props */}
        {/* 通过ref绑定react.createRef */}
        {/* <Son key={this.state.sonKey} ref={this.myRef} fatherData={this.state.sendState}></Son> */}
        {/* 通过re函数获取refs*/}
        {true && <Son key={this.state.sonKey} ref={this.setRefFn} fatherData={this.state.sendState}></Son>}
      </div>
    )
  }
}
